package com.hns.tool.pub;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.beanutils.PropertyUtils;
import org.springframework.util.StringUtils;

/**
 * 共通工具类
 * @author:wucx
 * @email:zhuangcaijin@126.com
 * @version Revision 2.0.0
 */
public class PubUtil {
    
    /**
     * 是否通过考勤表更新关系表的DRI_ID
     */
    public static final boolean IS_DRIVER_INTERFACE = true;
    /**
     * session 用户
     */
    public static final String SESSION_USER = "_ses_user_";
    /**
     * 布尔值-true
     */
    public static final String BOOLEAN_OF_TRUE = "1";
    /**
     * 布尔值-false
     */
    public static final String BOOLEAN_OF_FALSE = "0";

    /** 
     * 字符串分隔符 
     */
    public final static String STRING_SPLIT_COMMA = ",";

    /** 
     * 字符串引用字符 
     */
    public final static String STRING_SINGLE_QUOTES = "'";

    /** 
     * 空格常量 
     */
    public final static String STRING_BLANK_SPACE = " ";

    /** 
     * 任务状态－准备 
     */
    public final static int TASK_STATE_READY = 0;
    
    /** 
     * 任务状态－等待 
     */
    public final static int TASK_STATE_PENDING = 1;
    
    /** 
     * 任务状态－处理 
     */
    public final static int TASK_STATE_PROCESSING = 2;
    
    /** 
     * 任务状态－结账 
     */
    public final static int TASK_STATE_ACCOUNT_CLOSED = 3;
    
    /** 
     * 资源数据类型－组织机构类型 
     */
    public final static String RES_CTRL_ORG = "RES00001";
    
    /**
     * web根目录的本地路径
     * @param request 请求
     * @return 本地路径z字符串
     * @author:wucx
	 * @email:zhuangcaijin@126.com
     */
    public static String getWebRoot(HttpServletRequest request) {
        String webRoot = request.getSession().getServletContext().getRealPath("/");
        return webRoot;
    }
    
    /**
     * 项目临时目录
     * @param request 请求
     * @return 临时目录字符串
     * @author:wucx
	 * @email:zhuangcaijin@126.com
     */
    public static String getInterim(HttpServletRequest request) {
        String interimPath = getWebRoot(request) + "/interim/";
        return interimPath;
    }
    
    /**
     * 获取客户端ip地址
     * @param request 请求
     * @return ip地址
     * @author:JeffXu
     * @email:835264047@qq.com
     */
    public static String getRemortIP(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        
        return ip;
    }
    
    /**
     * 检查传入的参数是否为空。
     * @param value 传入的值
     * @return boolean 如果被检查值为null，返回true。
     * 如果value的类型为String，并且value.length()为0，返回true。
     * 如果value的类型为Object[]，并且value.length为0，返回true。
     * 如果value的类型为Collection，并且value.size()为0，返回true。
     * 如果value的类型为Dictionary，并且value.size()为0，返回true。
     * 如果value的类型为Map，并且value.size()为0，返回true。
     * @author:wucx
	 * @email:zhuangcaijin@126.com
     */
    public static boolean isEmpty(Object value) {
        if (value == null) {
            return true;
        }
        if ((value instanceof String) && (((String) value).trim().length() <= 0)) {
            return true;
        }
        if ((value instanceof Object[]) && (((Object[]) value).length <= 0)) {
            return true;
        }
        // 判断数组中的值是否全部为空null.
        if (value instanceof Object[]) {
            Object[] t = (Object[]) value;
            for (int i = 0; i < t.length; i++) {
                if (t[i] != null) {
                    return false;
                }
            }
            return true;
        }
        if ((value instanceof Collection) && ((Collection) value).size() <= 0) {
            return true;
        }
        if ((value instanceof Dictionary) && ((Dictionary) value).size() <= 0) {
            return true;
        }
        if ((value instanceof Map) && ((Map) value).size() <= 0) {
            return true;
        }
        return false;
    }
    
    /**
     * 检查传入的参数是否为非空。
     * @param value 传入的值
     * @return 如果非空 则true
     * @author:wucx
	 * @email:zhuangcaijin@126.com
     */
    public static boolean isNotEmpty(Object value) {
        return !PubUtil.isEmpty(value);
    }
    
    /**
     * 利用反射实现对象之间属性复制
     * @param from 
     * @param to 
     * @author:wucx
	 * @email:zhuangcaijin@126.com
     */
    public static void copyProperties(Object from, Object to) {
        try {
            copyPropertiesExclude(from, to, null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 复制对象属性
     * @param from 
     * @param to 
     * @param excludsArray 排除属性列表
     * @throws Exception
     * @author:wucx
	 * @email:zhuangcaijin@126.com
     */
    @SuppressWarnings("unchecked")
    public static void copyPropertiesExclude(Object from, Object to, String[] excludsArray) throws Exception {
        List<String> excludesList = null;
        if (excludsArray != null && excludsArray.length > 0) {
            excludesList = Arrays.asList(excludsArray); // 构造列表对象
        }
        Method[] fromMethods = from.getClass().getDeclaredMethods();
        if (PubUtil.isEmpty(fromMethods))
            fromMethods = from.getClass().getSuperclass().getDeclaredMethods();
        
        Method[] toMethods = to.getClass().getDeclaredMethods();
        if (PubUtil.isEmpty(toMethods))
            toMethods = to.getClass().getSuperclass().getDeclaredMethods();
        
        Map<String, Method> toMethodMap = Hashlize.hashlizeMap(toMethods, new HashKeyAdapter(new String[] {"name" }));
        
        if (PubUtil.isEmpty(fromMethods) || PubUtil.isEmpty(toMethodMap))
            return;
        
        Method fromMethod = null, toMethod = null;
        String fromMethodName = null, toMethodName = null;
        for (int i = 0; i < fromMethods.length; i++) {
            fromMethod = fromMethods[i];
            fromMethodName = fromMethod.getName();
            if (!fromMethodName.contains("get"))
                continue;
            
            // 排除列表检测
            if (excludesList != null && excludesList.contains(fromMethodName.substring(3).toLowerCase())) {
                continue;
            }
            
            toMethodName = "set" + fromMethodName.substring(3);
            toMethod = toMethodMap.get(toMethodName);
            if (toMethod == null)
                continue;
            
            Object value = fromMethod.invoke(from, new Object[0]);
            if (value == null)
                continue;
            
            // 集合类判空处理
            if (value instanceof Collection) {
                Collection newValue = (Collection) value;
                if (newValue.size() <= 0)
                    continue;
            }
            
            toMethod.invoke(to, new Object[] {value });
        }
    }
    
    /**
     * 对象属性值复制，仅复制指定名称的属性值
     * @param from
     * @param to
     * @param includsArray 包含属性列表
     * @throws Exception
     * @author:wucx
	 * @email:zhuangcaijin@126.com
     */
    @SuppressWarnings("unchecked")
    public static void copyPropertiesInclude(Object from, Object to, String[] includsArray) throws Exception {
        List<String> includesList = null;
        if (includsArray != null && includsArray.length > 0) {
            includesList = Arrays.asList(includsArray); // 构造列表对象
        } else {
            return;
        }
        
        Method[] fromMethods = from.getClass().getDeclaredMethods();
        Map<String, Method> toMethodMap = Hashlize.hashlizeMap(to.getClass().getDeclaredMethods(), new HashKeyAdapter(new String[] {"name" }));
        Method fromMethod = null, toMethod = null;
        String fromMethodName = null, toMethodName = null;
        for (int i = 0; i < fromMethods.length; i++) {
            fromMethod = fromMethods[i];
            fromMethodName = fromMethod.getName();
            if (!fromMethodName.contains("get"))
                continue;
            
            // 排除列表检测
            String str = fromMethodName.substring(3);
            if (!includesList.contains(str.substring(0, 1).toLowerCase() + str.substring(1))) {
                continue;
            }
            
            toMethodName = "set" + fromMethodName.substring(3);
            toMethod = toMethodMap.get(toMethodName);
            if (toMethod == null)
                continue;
            Object value = fromMethod.invoke(from, new Object[0]);
            if (value == null)
                continue;
            
            // 集合类判空处理
            if (value instanceof Collection) {
                Collection newValue = (Collection) value;
                if (newValue.size() <= 0)
                    continue;
            }
            toMethod.invoke(to, new Object[] {value });
        }
    }
    
    /**
     * map按key值复值value到类属性
     * @param from map
     * @param to 目标对象
     * @author:wucx
	 * @email:zhuangcaijin@126.com
     */
    public static void copyProperties(Map from, Object to) {
        if (PubUtil.isEmpty(from))
            return;
        
        if (PubUtil.isEmpty(to))
            throw new RuntimeException("targe object is null");
        
        Iterator entries = ((Map) from).entrySet().iterator();
        while (entries.hasNext()) {
            Map.Entry entry = (Map.Entry) entries.next();
            String name = getPropertyNameByKey(entry.getKey().toString().toLowerCase(), "_");
            try {
                // oracle
                if (name.equals("rownum")) {
                    continue;
                }
                PropertyUtils.setSimpleProperty(to, name, entry.getValue());
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e.getMessage(), e);
            } catch (InvocationTargetException e) {
                throw new RuntimeException(e.getMessage(), e);
            } catch (NoSuchMethodException e) {
                throw new RuntimeException(e.getMessage(), e);
            }
        }
        
    }
    
    /**
     * 把Map转换成对像(按key->property)
     * @param from 
     * @param targetCLZ 目标类型
     * @return 转换为目标类型对象的list
     * @author:wucx
	 * @email:zhuangcaijin@126.com
     */
    @SuppressWarnings("unchecked")
    public static List convertListMapToObject(List<Map> from, Class targetCLZ) {
        if (PubUtil.isEmpty(from))
            return null;
        
        List resultList = new ArrayList();
        for (Map map : from) {
            Object targetInst = null;
            try {
                targetInst = targetCLZ.newInstance();
                copyProperties(map, targetInst);
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            
            resultList.add(targetInst);
        }
        
        return resultList;
    }
    
    @SuppressWarnings("unchecked")
    public static Object convertMapToObject(Map map, Class targetCLZ) {
        if (PubUtil.isEmpty(map))
            return null;
        
        Object targetInst = null;
        try {
            targetInst = targetCLZ.newInstance();
            copyProperties(map, targetInst);
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        
        return targetInst;
    }
    
    /**
     * 把key转换属性名(删除split字符，split后第一个字符变成大写)
     * @param key
     * @param split 标记，其后第一个字符变成大写
     * @return 属性名字符串
     * @author:wucx
	 * @email:zhuangcaijin@126.com
     */
    public static String getPropertyNameByKey(String key, String split) {
        if (PubUtil.isEmpty(key))
            return null;
        
        if (key.indexOf(split) <= 0)
            return key;
        
        String[] keys = key.split(split);
        String result = "";
        for (int i = 0; i < keys.length; i++) {
            if (i > 0) {
                keys[i] = keys[i].substring(0, 1).toUpperCase() + keys[i].substring(1);
            }
            result = result + keys[i];
        }
        
        return result;
    }
    
    /**
     * 将字符串数组(List)的元素以指定连接符unionChar拼接成字符串，每个数组元素前后都将添加appendChar。
     * <p>
     * <strong>用例描述：</strong>
     * 
     * <pre>
     * getUnionStr(new String[] {&quot;A&quot;, &quot;B&quot;, &quot;C&quot; }, &quot;,&quot;, &quot;&quot;) = &quot;A,B,C&quot;;
     * getUnionStr(new String[] {&quot;A&quot;, &quot;B&quot;, &quot;C&quot; }, &quot;,&quot;, &quot;*&quot;) = &quot;*A*,*B*,*C*&quot;;
     * </pre>
     * @param strCols 用于连接的字符串数组
     * @param unionChar 用来连接的中间字符
     * @param appendChar 用来在每个字符中追加
     * @return
     * @author:wucx
	 * @email:zhuangcaijin@126.com
     */
    public static String getUnionString(Collection<String> strCols, String unionChar, String appendChar) {
        if (PubUtil.isEmpty(strCols))
            return null;
        
        StringBuffer ret = new StringBuffer();
        int i = 0;
        for (String str : strCols) {
            if (i != 0)
                ret.append(unionChar);
            ret.append(appendChar + str + appendChar);
            i++;
        }
        
        return ret.toString();
    }
    
    public static String getUnionSQLStr(String str) {
        return STRING_SINGLE_QUOTES + str + STRING_SINGLE_QUOTES;
    }
    
    /**
     * 组合适合in 的SQL的字符串
     */
    public static String getUnionSQLStr(List<String> strList) {
        return getUnionString(strList, STRING_SPLIT_COMMA, STRING_SINGLE_QUOTES);
    }
    
    public static String getUnionSQLString(Collection<String> strcols) {
        return getUnionString(strcols, STRING_SPLIT_COMMA, STRING_SINGLE_QUOTES);
    }
    
    public static String getUnionSQLStr(String[] strs) {
        return UtilString.getUnionStr(strs, STRING_SPLIT_COMMA, STRING_SINGLE_QUOTES);
    }
    
    /**
     * 取反数据库值
     * @param value
     * @return 结果
     * @author:wucx
	 * @email:zhuangcaijin@126.com
     */
    public static BigDecimal getNegDoubleValue(BigDecimal value) {
        if (value == null || value.toString() == null)
            return null;
        
        return SafeCompute.sub(BigDecimal.ZERO, value);
    }
    
    /**
     * 安全比较
     * @param d1 比较值1
     * @param d2 比较值2
     * @return -1 值2大，0 一样大， 1 值1大
     * @author:wucx
	 * @email:zhuangcaijin@126.com
     */
    public static int safeCompare(BigDecimal d1, BigDecimal d2) {
        d1 = (d1 == null) ? new BigDecimal(0) : d1;
        d2 = (d2 == null) ? new BigDecimal(0) : d2;
        
        return d1.compareTo(d2);
    }
    
    public static boolean isTrue(String value) {
        if (PubUtil.isEmpty(value))
            return false;
        
        if (BOOLEAN_OF_TRUE.equals(value))
            return true;
        else
            return false;
    }
    
    public static boolean isFalse(String value) {
        if (PubUtil.isEmpty(value))
            return true;
        
        if (BOOLEAN_OF_FALSE.equals(value))
            return true;
        else
            return false;
    }
    /**
     * 过滤null
     * @param target 传入的对象
     * @return 过滤后的结果
     * @author:wucx
	 * @email:zhuangcaijin@126.com
     */
    public static String filterNULL(Object target) {
        if (isNotEmpty(target)) {
            return target.toString();
        } else {
            return "";
        }
    }
    
    /**
     * 过滤空格
     * @param target 传入的对象
     * @return 过滤后的结果
     * @author:wucx
	 * @email:zhuangcaijin@126.com
     */
    public static String filterNULLSPACE(Object target) {
        if (isNotEmpty(target)) {
            return StringUtils.trimWhitespace(target.toString());
        } else {
            return "";
        }
    }
    
    /**
     * 过滤全部空格 
     * @param target 传入的对象
     * @return 过滤后的结果
     * @author:wucx
	 * @email:zhuangcaijin@126.com
     */
    public static String filterNULLAllSPACE(Object target) {
        if (isNotEmpty(target)) {
            return StringUtils.trimAllWhitespace(target.toString());
        } else {
            return "";
        }
    }
    
    /**
     * 将指定对象list转换为以map<String,Object>为元素的list,其中map中key为属性名字符串，value为属性值
     * @param list 指定对象list
     * @return 转换成以map为元素的list
     * @author:zhangyu
     * @email:zhangyu2222z@sina.cn
     */
    public static <T> List<Map<String, Object>> convertObjectToListMap(List<T> list){
    	List<Map<String, Object>> mapList = new ArrayList<Map<String,Object>>();
    	for(int i=0;i<list.size();i++){
    		Map<String, Object> map = new HashMap<String, Object>();
    		T t = list.get(i);
    		Class<? extends Object> clazz = t.getClass();
    		Field[] fields = clazz.getDeclaredFields();
    		for(int j=0;j<fields.length;j++){
    			try {
    				Field field = fields[j];
    				field.setAccessible(true);
    				map.put(field.getName(), field.get(t));
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				}
    		}
    		mapList.add(map);
    	}
    	return mapList;
    }
    
}
